1 隐式类型转换;
2 赋值语句中的类型转换;
3 显示类型转换(强制类型转换)
3.1 旧风格
(new-type) expression
new-type (expression)
3.2 新风格
tatic_cast、dynamic_cast、const_cast、reinterpret_cast。
static_cast与dynamic_cast:把这两个放在一起比较容易记忆,"一静一动"。从字面上也可以看出,前者提供的是编译时期的静态类型检测,后者提供的是运行时检测。
const_cast用于去除指针和引用的常量性,不能去除变量的常量性。
reinterpret_cast这种强制类型转换是一种非常强的强制类型转换,它可以将任意两个无关的指针或引用进行转换。上面的static_cast进行强制类型转换时,会进行编译时的类型安全检查,即你可以将int转成float,将子类引用(指针)转成父类引用(指针),子转父和父转子都可以,但父转子不安全。但是你不能使用static_cast将两个无关的东西进行转换,比如两个无关的类,因为编译器在编译的时候会检查这个转换是否可行,很明显不可行。
dynamic_cast既然是动态安全性检查,那么它肯定只能应用于指针或引用,不能用于内置的数据类型转换(内置的数据类型转换,在编译阶段由static_cast检查即可)。dynamic_cast不但检查两个指针是否属于同一个继承树(static_cast也检查这个),还会检测这种转换是否可行。如果可行就会返回一个新指针,并计算出为处理多继承的需要的必要的偏移量。如果不可行会返回NULL。因此即使我们使用reinterpret_cast强制类型转换骗过编译器编译成功,如果我们在使用前再使用dynamic_cast转换检测一下的话,还是能发现这个错误的转换的。
static_cast会进行静态的安全性检查,一般用于内置数据类型的转换和通常的类之间的转换。
const_cast主要是用来去掉指针和引用的const和volatile类型。
reinterpret_cast用于完全没有关系指针或引用之间的转换,比如字符指针转整形指针。
dynamic_cast通常用于基类和派生类之间的相互转换。
1. 隐式类型转换
char c = 'A'; int i = c; //隐式类型转换 int foo(int n) { return c;//隐式类型转换 } int main(void){ foo(c); //隐式类型转换 }
2.显示类型转换
2.1 C 语言显示类型转换(强制类型转换)
int a = 0xE0200080; int *p = (int *)a; char c; int i = (int)c; //C 风格的强制转换 int i = int(c); //C++风格的强制转换
2.2 C++语言显示类型转换
兼容 C 语言类型转换的同时增加了四种操作符的形式。
(1) 静态类型转换
目标类型变量 = static_cast<目标类型>(源类型变量);
主要用于将 void* 转化为其它类型的指针
int a; void* pv = &a; int* pi = static_cast(pv); //ok double* pv = static_cast (pi); //error
A 类型 ==> B 类型可以隐式转换
B 类型 ==> A 类型可以静态转换
(2) 动态类型转换
目标类型变量 = dynamic_cast<目标类型>(源类型变量);
主要用于将基类的指针或引用安全地转换成派生类的指针或引用,并用派生类的指针或引用调用非虚函数。
(3) 常量类型转换
目标类型变量 = const_cast<目标类型>(源类型变量);
主要用于去除指针或引用的常属性。
const int a = 10; const int* p = &a; *p = 20; //error int* p2 = const_cast(p); *p2 = 20; //ok const int& r = a; r = 30; //error int& r2 = const_cast (r); r2 = 30; //ok
(4) 重解释类型转换
目标类型变量 = reinterpret_cast<目标类型>(源类型变量);
A.任意类型的指针或引用之间进行转换
B.在指针和整型数之间的转换
int a; int* pa = &a; double* pd = reinterpret_cast(pa);
在执行“double dbRate = 10 / 3;”语句后变量dbRate的值是多少呢?10除以3,理论上为3.33333…,但是由于10和3均是整型,其运算结果也为整型,因此10 / 3在计算机中的结果为3,将结果3赋值给double类型,dbRate的结果为3.0000…。这就是采用了C++默认的数值转换规则,它通常不符合我们的逻辑(我们的预期结果是3.33333…)。为此就需要强制类型转换替换C++默认的数值转换规则。在C++中有两种强制类型转换方式,一种是使用C语言提供的原始的强制类型转换,另一种是C++语言引入的新的强制类型转换。
数据类型 (表达式)
(数据类型) 表达式
double dbRate = static_cast
C++形式的强制类型转换有一些安全性的限制。例如:使用C语言的强制类型转换能够将整型指针转换为结构体类型指针,而static_cast则不允许进行这样的转换。
Student* boy = static_cast
动态转换也是C++语言提供的一种强制类型转换方式。与静态转换不同的是在转换前它能够进行类型检查。动态转换通常用于一个类对象指针转换为另一个类对象指针。如果源指针类型与目标指针类型不兼容,则转换的结果为NULL。程序中可以通过检测结果是否为NULL来判断强制类型转换是否成功。在C++中使用dynamic_cast关键字进行动态转换。动态转换只能对void*(无类型指针)类型或者类对象指针进行转换,并且类中必须包含有虚方法,而不能对普通的数据类型进行转换。
常量转换用于将const对象转换为非const对象。
重解释转换能够将任何指针类型转换为其他的指针类型,这种转换方式是一种不安全的转换方式。在应用程序中尽量少使用重解释转换。在C++中使用reinterpret_cast关键字实现重解释转换。下面的语句利用重解释转换将一个指针转换为无符号整数指针。
Casting is a conversion process wherein data can be changed from one type to another. C++ has two types of conversions:
Implicit conversion: Conversions are performed automatically by the compiler without the programmer's intervention.
int iVariable = 10; float fVariable = iVariable; //Assigning an int to a float will trigger a conversion.
Explicit conversion: Conversions are performed only when explicitly specified by the programmer.
int iVariable = 20; float fVariable = (float) iVariable / 10;
In C++, there are four types of casting operators.
- static_cast - const_cast - reinterpret_cast - dynamic_cast
In this article we will only be looking into the first three casting operators as dynamic_cast is very different and is almost exclusively used for handling polymorphism only which we will not be addressing in this article.
static_cast
Format:
static_cast
float fVariable = static_cast(iVariable); /*This statement converts iVariable which is of type int to float. */
By glancing at the line of code above, you will immediately determine the purpose of the cast as it is very explicit. The static_cast tells the compiler to attempt to convert between two different data types. It will convert between built-in types, even when there is a loss of precision. In addition, the static_cast operator can also convert between related pointer types.
int* pToInt = &iVariable; float* pToFloat = &fVariable; float* pResult = static_cast(pToInt); //Will not work as the pointers are not related (they are of different types).
const_cast
Format:
const_cast
void aFunction(int* a) { cout << *a << endl; } int main() { int a = 10; const int* iVariable = &a; aFunction(const_cast(iVariable)); /*Since the function designer did not specify the parameter as const int*, */ // we can strip the const-ness of the pointer iVariable to pass it into the function. Make sure that the function will not modify the value. return 0; }
Probably one of the most least used cast, the const_cast does not cast between different types. Instead it changes the "const-ness" of the expression. It can make something const what was not const before, or it can make something volatile/changeable by getting rid of the const. Generally speaking, you will not want to utilise this particular cast in your programs. If you find yourself using this cast, you should stop and rethink your design.
reinterpret_cast
Format:
reinterpret_cast
Arguably one of the most powerful cast, the reinterpret_cast can convert from any built-in type to any other, and from any pointer type to another pointer type. However, it cannot strip a variable's const-ness or volatile-ness. It can however convert between built in data types and pointers without any regard to type safety or const-ness. This particular cast operator should be used only when absolutely necessary.
Hopefully this article was helpful to anyone whose struggling to grasp the theory of casting.
Happy programming.
static_cast has basically the same power and meaning as the general-purpose C-style cast. It also has the same kind of restrictions. Forexample, you can’t cast a struct into an int or a double into a pointer using static_cast any more than you can with a C-style cast.Furthermore, static_cast can’t remove constness from an expression,because another new cast, const_cast, is designed specificallyto do that.
The other new C++ casts are used for more restricted purposes.const_cast is used to cast away the constness or volatileness of an expression. By using a const_cast, you emphasize (to both humansand compilers) that the only thing you want to change through the cast is the constness or volatileness of something. This meaning is enforced by compilers. If you try to employ const_cast for anything other than modifying the constness or volatileness of anexpression, your cast will be rejected.
static_cast converts between related types such as one pointer type to another in the same class hierarchy, an integral type to an enumeration, or a floating-point type to an integral type. It also does conversions defined by constructors and conversion operators .
reinterpret_cast handles conversions between unrelated types such as an integer to a pointeror a pointer to an unrelated pointer type.
const_cast converts between types that differ only in const and volatile qualifiers.
dynamic_cast does run-time checked conversion of pointers and references into a class hierarchy.These distinctions among the named casts
These distinctions among the named casts allow the compiler to apply some minimal type checking and make it easier for a programmer to find the more dangerous conversions represented as reinterpret_ casts. Some static_casts are portable, but few reinterpret_casts are. Hardly any guarantees are made for reinterpret_cast, but generally it produces a value of a new type that has the same bit pattern as its argument. If the target has at least as many bits as the original value, we can reinterpret_ cast the result back to its original type and use it. The result of a reinterpret_cast is guaranteed to be usable only if its result is converted back to the exact original type. Note that reinterpret_cast is the kind of conversion that must be used for pointers to functions.
From C, C++ inherited the notation (T)e, which performs any conversion that can be expressed as a combination of static_casts, reinterpret_casts, const_casts to make a value of type T from the expression e (§44.2.3). Unfortunately, the C-style cast can also cast from a pointer to a class to a pointer to a private base of that class. Never do that, and hope for a warning from the compiler if you do it by mistake. This C-style cast is far more dangerous than the named conversion operators because the notation is harder to spot in a large program and the kind of conversion intended by the programmer is not explicit. That is, (T)e might be doing a portable conversion between related types, a nonportable conversion between unrelated types, or removing the const modifier from a pointer type. Without knowing the exact types of T and e, you cannot tell.